/**
 * 签到路由
 * 处理签到、签退、补签、统计等核心业务功能
 */

import { FastifyPluginAsync } from 'fastify'
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
import {
    PerformCheckInSchema,
    CheckInResultSchema,
    PerformCheckOutSchema,
    ManualCheckInSchema,
    EventStatisticsSchema,
    CheckInHistoryQuerySchema,
    CheckInHistoryResponseSchema,
    InitializeCheckInSchema,
    InitializeResultSchema
} from '../validators/checkin.schema'
import {
    performCheckIn,
    performCheckOut,
    manualCheckIn,
    getEventCheckInSummary,
    getMemberCheckInHistory,
    initializeEventCheckInRecords
} from '../services/checkin.service'
import { requireOwnerOrAdmin } from '../plugins/auth.plugin'
import type { CheckInDTO, CheckOutDTO, ManualCheckInDTO, AttendanceRecordDTO } from '@services/common/types'

const checkinRoutes: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
    const server = fastify.withTypeProvider<TypeBoxTypeProvider>()

    /**
     * 执行签到
     * POST /api/checkin/perform
     */
    server.post(
        '/api/checkin/perform',
        {
            schema: {
                description: '成员执行签到',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                body: PerformCheckInSchema,
                response: {
                    200: CheckInResultSchema,
                    201: CheckInResultSchema
                }
            },
            preHandler: [server.authenticate, server.requireMember]
        },
        async (request, reply) => {
            const body = request.body

            // 确保 memberId 与当前登录用户一致（成员只能为自己签到）
            if (request.user && body.memberId !== request.user.userId) {
                throw new Error('您只能为自己签到')
            }

            // 转换 DTO：checkInTime 从 string 转为 Date, location 类型断言
            const dto: CheckInDTO = {
                eventId: body.eventId!,
                memberId: body.memberId!,
                location: body.location as { latitude: number; longitude: number; accuracy?: number } | undefined,
                photo: body.photo,
                secretCode: body.secretCode,
                checkInTime: body.checkInTime ? new Date(body.checkInTime) : undefined
            }

            const result = await performCheckIn(dto)

            if (!result.success) {
                throw new Error(result.message || '签到失败')
            }

            // 判断是新建还是更新
            const statusCode = result.data?.eventRecordId ? 200 : 201

            return reply.status(statusCode).send({
                success: true,
                data: result.data
            })
        }
    )

    /**
     * 执行签退
     * POST /api/checkin/checkout
     */
    server.post(
        '/api/checkin/checkout',
        {
            schema: {
                description: '成员执行签退',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                body: PerformCheckOutSchema,
                response: {
                    200: CheckInResultSchema
                }
            },
            preHandler: [server.authenticate, server.requireMember]
        },
        async (request, reply) => {
            const body = request.body

            // 确保 memberId 与当前登录用户一致
            if (request.user && body.memberId !== request.user.userId) {
                throw new Error('您只能为自己签退')
            }

            // 转换 DTO
            const dto: CheckOutDTO = {
                eventInstanceId: body.eventInstanceId!,
                memberId: body.memberId!,
                checkOutTime: body.checkOutTime ? new Date(body.checkOutTime) : undefined,
                reason: body.reason
            }

            const result = await performCheckOut(dto)

            if (!result.success) {
                throw new Error(result.message || '签退失败')
            }

            return reply.send({
                success: true,
                data: result.data
            })
        }
    )

    /**
     * 管理员补签
     * POST /api/checkin/manual
     */
    server.post(
        '/api/checkin/manual',
        {
            schema: {
                description: '管理员为成员补签（需要协管权限）',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                body: ManualCheckInSchema,
                response: {
                    200: CheckInResultSchema,
                    201: CheckInResultSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const body = request.body

            // 转换 DTO
            const dto: ManualCheckInDTO = {
                eventId: body.eventId!,
                memberId: body.memberId!,
                status: body.status!,
                reason: body.reason!,
                adminId: body.adminId!
            }

            // 注意：权限验证在 service 层进行（需要知道 organizationId）
            const result = await manualCheckIn(dto)

            if (!result.success) {
                throw new Error(result.message || '补签失败')
            }

            const statusCode = result.code === 201 ? 201 : 200

            return reply.status(statusCode).send({
                success: true,
                data: result.data
            })
        }
    )

    /**
     * 获取事件签到汇总
     * GET /api/checkin/summary/:eventId
     */
    server.get(
        '/api/checkin/summary/:eventId',
        {
            schema: {
                description: '获取事件的签到统计汇总（需要协管权限）',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        eventId: { type: 'string', format: 'uuid' }
                    },
                    required: ['eventId']
                },
                response: {
                    200: EventStatisticsSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { eventId } = request.params as { eventId: string }
            const adminId = request.user!.userId

            const result = await getEventCheckInSummary(eventId, adminId)

            if (!result.success) {
                throw new Error(result.message || '获取统计失败')
            }

            return reply.send({
                success: true,
                data: result.data
            })
        }
    )

    /**
     * 获取成员签到历史
     * GET /api/checkin/history/:memberId
     */
    server.get(
        '/api/checkin/history/:memberId',
        {
            schema: {
                description: '获取成员的签到历史记录（成员只能查看自己，管理员可查看所有）',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        memberId: { type: 'string', format: 'uuid' }
                    },
                    required: ['memberId']
                },
                querystring: CheckInHistoryQuerySchema,
                response: {
                    200: CheckInHistoryResponseSchema
                }
            },
            preHandler: [server.authenticate]
        },
        async (request, reply) => {
            const { memberId } = request.params as { memberId: string }
            const query = request.query as any

            // 权限验证：成员只能查看自己，管理员可查看所有
            await requireOwnerOrAdmin(request, memberId)

            const result = await getMemberCheckInHistory(memberId, {
                eventId: query.eventId,
                status: query.status,
                startDate: query.startDate ? new Date(query.startDate) : undefined,
                endDate: query.endDate ? new Date(query.endDate) : undefined,
                offset: query.offset || 0,
                limit: query.limit || 20
            })

            if (!result.success) {
                throw new Error(result.message || '获取历史记录失败')
            }

            // 转换 Date 为 ISO string
            const transformedData = result.data
                ? {
                      data: result.data.data.map((record: AttendanceRecordDTO) => ({
                          ...record,
                          checkInTime: record.checkInTime?.toISOString(),
                          checkOutTime: record.checkOutTime?.toISOString()
                      })),
                      total: result.data.total,
                      offset: result.data.offset,
                      limit: result.data.limit,
                      hasMore: result.data.hasMore
                  }
                : undefined

            return reply.send({
                success: true,
                data: transformedData
            })
        }
    )

    /**
     * 批量初始化签到记录
     * POST /api/checkin/initialize/:eventId
     */
    server.post(
        '/api/checkin/initialize/:eventId',
        {
            schema: {
                description: '为活动批量初始化签到记录（需要管理员权限）',
                tags: ['签到'],
                security: [{ bearerAuth: [] }],
                params: {
                    type: 'object',
                    properties: {
                        eventId: { type: 'string', format: 'uuid' }
                    },
                    required: ['eventId']
                },
                body: InitializeCheckInSchema,
                response: {
                    200: InitializeResultSchema
                }
            },
            preHandler: [server.authenticate, server.requireAdmin]
        },
        async (request, reply) => {
            const { eventId } = request.params as { eventId: string }
            const { source } = request.body

            const result = await initializeEventCheckInRecords(eventId, source)

            if (!result.success) {
                throw new Error(result.message || '初始化失败')
            }

            return reply.send({
                success: true,
                data: result.data
            })
        }
    )
}

export default checkinRoutes

// fastify-autoload will use this exported 'prefix' when mounting the plugin
export const prefix = '/api/checkin'
